package com.fabriciojf.snmp;

import java.io.IOException;

import java.util.ArrayList;
import java.util.List;
import org.apache.log4j.*;

import org.snmp4j.CommunityTarget;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.PDU;
import org.snmp4j.smi.Address;
import org.snmp4j.smi.Integer32;
import org.snmp4j.smi.Null;
import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.OID;
import org.snmp4j.smi.UdpAddress;
import org.snmp4j.smi.VariableBinding;
import org.snmp4j.Snmp;
import org.snmp4j.transport.DefaultUdpTransportMapping;
import org.snmp4j.TransportMapping;

/**
 * Classe utilitaria contendo os gets de dados do protocolo SNMP 
 * 
 * @author Fabricio fabriciojf@gmail.com
 * @since 07/05/2010
 * @version 1.0.0
 */
public class SNMP {

	/**
	 * Retorna um lista contendo os subitens do OID requisitado
	 * 
	 * @param endereco ip do client que contem o SNMP agent
	 * @param porta SNMP por default 161
	 * @param OID requisitado ex: 1.3.6.1.4.1.2021.4.5.0 total de RAM
	 * @return lista de OIDs
	 */
    public List<String> getNext(String endereco, String porta, String oid) {
        return getParam(endereco, porta, oid, PDU.GETNEXT);
    }

    /**
	 * Retorna um strting contendo o OID requisitado
	 * 
	 * @param endereco ip do client que contem o SNMP agent
	 * @param porta SNMP por default 161
	 * @param OID requisitado ex: 1.3.6.1.4.1.2021.4.5.0 total de RAM
	 * @return string contendo o OID
	 */
    public String get(String endereco, String porta, String oid) {
        String retorno =  getParam(endereco, porta, oid, PDU.GET).get(1);
        String limp = retorno.substring(retorno.indexOf("=") + 1, retorno.length());
        return limp;
    }

    /**
	 * Retorna uma lista contendo os OIDs requisitados
	 * 
	 * @param endereco ip do client que contem o SNMP agent
	 * @param porta SNMP por default 161
	 * @param OID requisitado ex: 1.3.6.1.4.1.2021.4.5.0 total de RAM
	 * @return lista de OIDs
	 */
    @SuppressWarnings("deprecation")
	public List<String> getParam(String endereco, String porta,
            String oid, int get) {
        
        Address targetAddress = new UdpAddress(endereco + "/" + porta);
        OID targetOID = new OID(oid);
        List<String> resultSnmp = new ArrayList<String>();

        Logger.getRootLogger().setLevel(Level.OFF);

        PDU requestPDU = new PDU();
        requestPDU.add(new VariableBinding(targetOID));
        requestPDU.setType(get);
        
        CommunityTarget target = new CommunityTarget();
        target.setCommunity(new OctetString("public"));
        target.setAddress(targetAddress);
        target.setVersion(SnmpConstants.version1);

        try {
            TransportMapping transport = new DefaultUdpTransportMapping();
            Snmp snmp = new Snmp(transport);
            transport.listen();

            boolean finished = false;

            while (!finished) {
                VariableBinding vb = null;

                PDU responsePDU = snmp.sendPDU(requestPDU, target);
                if (responsePDU != null) {
                    vb = responsePDU.get(0);
                }

                if (responsePDU == null) {
                    resultSnmp.add("responsePDU == null");
                    finished = true;
                } else if (responsePDU.getErrorStatus() != 0) {
                    resultSnmp.add("responsePDU.getErrorStatus() != 0");
                    resultSnmp.add(responsePDU.getErrorStatusText());
                    finished = true;
                } else if (vb.getOid() == null) {
                    resultSnmp.add("vb.getOid() == null");
                    finished = true;
                } else if (vb.getOid().size() < targetOID.size()) {
                    resultSnmp.add("vb.getOid().size() < targetOID.size()");
                    finished = true;
                } else if (targetOID.leftMostCompare(targetOID.size(),
                        vb.getOid()) != 0) {
                    resultSnmp.add("targetOID.leftMostCompare() != 0)");
                    finished = true;
                } else if (Null.isExceptionSyntax(vb.getVariable().getSyntax())) {
                    resultSnmp.add(
                            "Null.isExceptionSyntax(vb.getVariable().getSyntax())");
                    finished = true;
                } else if (vb.getOid().compareTo(targetOID) <= 0) {
                    resultSnmp.add("Variable received is not " +
                            "lexicographic successor of requested " +
                            "one:");
                    resultSnmp.add(vb.toString());
                    finished = true;

                } else {
                    // Dump response.
                    resultSnmp.add(vb.toString());

                    // Set up the variable binding for the next entry.
                    requestPDU.setRequestID(new Integer32(0));
                    requestPDU.set(0, vb);
                }
            }
            snmp.close();
        } catch (IOException e) {
            System.out.println("IOException: " + e);
        }
        return resultSnmp;
    }
}
